#pragma once
#include "common.hpp"
#include "Log.hpp"
#include "Socket.hpp"
#include "InetAddr.hpp"
#include "TcpServer.hpp"
#include "Util.hpp"
#include <unordered_map>


using namespace SocketModule;
using namespace LogModule;

const std::string gap = " ";
const std::string gspace = "\r\n";

const std::string webroot = "./wwwroot/";
const std::string page_404 = "/404.html";
const std::string homepage = "index.html";

class HttpResponse
{
public:
    HttpResponse():
        _blankline(gspace),
        _version ("HTTP/1.1")
    {}

   std::string Serialize()
   {
        std::string status_line = _version + gap + std::to_string(_code) + gap + _desc + _blankline;
        std::string resp_header;
        for(auto& s : _headers)
        {
            std::string line = s.first + ": " + s.second + _blankline;
            resp_header += line;
        }

        return status_line + resp_header + _blankline + _text;
   } 

   //返回文件类型
   std::string Uri2Suffix(std::string& path)
   {
        auto pos = path.rfind('.');
        if(pos == std::string::npos)
            return "text/html"; //如果没找到默认返回首页类型
        
        std::string suffix = path.substr(pos);
        if(suffix == ".html"  || suffix == ".htm")
        {
            return "text/html";
        }
        else if (suffix == ".jpg")
        {
            return "image/jpeg";
        }
        else if (suffix == "/png")
            return "image/png";
        else
            return  "text/html";
   }

   void  SetHeader(const std::string& key,const std::string& value)
   {
        if(_headers.count(key))
            return;
        else
        {
            _headers.insert(std::make_pair(key,value));//将当前报头插入到哈希表内
        }
   }

   bool MakeResponse()
   {
        int filesize = 0;
        bool res = Util::ReadFileContent(_targetfile,&_text);
        if(!res)
        {
            _text = "";
            LOG(LogLevel::WARNING) << "client want get: "  << _targetfile << ", but not found";
            SetCode(404);
            _targetfile = webroot + page_404;
            filesize = Util::FileSize(_targetfile);
            Util::ReadFileContent(_targetfile, &_text);
            std::string suffix = Uri2Suffix(_targetfile);//  确定正文部分文件类型   设置报头 content-type 
            SetHeader("Content-Type",suffix);
            SetHeader("Content-Length",std::to_string(filesize));
        }  
        else
        {
            SetCode(200);
            filesize = Util::FileSize(_targetfile);
            std::string suffix = Uri2Suffix(_targetfile);
            SetHeader("Conent-Type", suffix);
            SetHeader("Content-Length", std::to_string(filesize));
        }
        return true;
    }

   void SetTargetFile(const std::string& targetfile)
   {
        _targetfile = targetfile;
   }

   void SetCode(int code)
   {
        _code = code;
        switch(_code)
        {
            case(404):
                _desc = "Not Found";
                break;
            case(200):
                _desc = "OK";
                break;
            default:
                break;
        }
   }

private:
    std::string _version;//版本
    int _code;//错误码
    std::string _desc;//描述

    std::unordered_map<std::string,std::string> _headers;
    std::string _blankline;
    std::string _text; //正文
    
    std::string _targetfile; //客户端请求的文件路径

};


class HttpRequeset
{
public:
    HttpRequeset(){}

    std::string Serialize()
    {
        return std::string();
    }

    void PraseOneLine(std::string& OneLine)
    {
        std::stringstream ss(OneLine);
        ss  >> _method
            >> _url
            >> _version;
    }

    bool DeSerialize(std::string& BigStringRromInternet)
    {
        std::string OneLine;
        Util::GetOneLineFromBigString(BigStringRromInternet,&OneLine,gspace);
        LOG(LogLevel::DEBUG) << OneLine;

        //反序列化
        PraseOneLine(OneLine);

        if(_url == "/")
            _url = webroot + homepage;
        else
            _url = webroot + _url;

        LOG(LogLevel::DEBUG) << _url;
    
        return true;
    };

    std::string GetRequsetUrl(){    return _url; }

    ~HttpRequeset(){}

private:
    std::string _method;
    std::string _url;
    std::string _version;

    std::unordered_map<std::string, std::string> _headers;
    std::string _blankline;
    std::string _text;
    
};

class Http
{
public:
    Http(uint16_t port)
        :tsvr(std::make_unique<TcpServer>(port))
    {

    }
 
    void HanderHttpRequest(std::shared_ptr<Socket>& sockfd, InetAddr& client)
    {
        std::string BigStringRromInternet;
        int n = sockfd->Recv(&BigStringRromInternet);
        if(n > 0)
        {
            //将得到的大字符串反序列化
            HttpRequeset req;
            req.DeSerialize(BigStringRromInternet);

            //此时req的url存储着客户端想要访问的网站的html路径
            HttpResponse resp;
            //设置resp中的目标路径
            resp.SetTargetFile(req.GetRequsetUrl());
            //做出回应
            resp.MakeResponse();
        
            std::string response_str = resp.Serialize();
            sockfd->Send(response_str);
        }


// #ifndef DEBUG
// #define DEBUG
//         std::string http_req;
//         sockfd->Recv(&http_req);
//         std::cout << http_req;
// #endif
    }

    void Start()
    {
        tsvr->Start([this](std::shared_ptr<Socket>& sockfd, InetAddr& client){
            this->HanderHttpRequest(sockfd,client);
        });
    }

private:
    std::unique_ptr<TcpServer> tsvr;
};